package com.tiancheng.trade.order.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tiancheng.trade.commom.core.data.PageInfo;
import com.tiancheng.trade.commom.core.data.Result;
import com.tiancheng.trade.commom.core.data.notify.PaySubFlowResultMsgBO;
import com.tiancheng.trade.commom.core.enums.VerificationStatusEnum;
import com.tiancheng.trade.commom.core.exception.BusinessException;
import com.tiancheng.trade.commom.core.exception.error.BusinessErrorInfoEnum;
import com.tiancheng.trade.commom.core.utils.JsonUtil;
import com.tiancheng.trade.order.bo.SubOrderBO;
import com.tiancheng.trade.order.bo.SubOrderRefundBO;
import com.tiancheng.trade.order.bo.cmq.ScrmSubOrders;
import com.tiancheng.trade.order.bo.cmq.VipMsgBO;
import com.tiancheng.trade.order.bo.excel.ExportExcelBO;
import com.tiancheng.trade.order.bo.excel.ExportSubOrderBo;
import com.tiancheng.trade.order.bo.excel.ExportSubOrderRefundBo;
import com.tiancheng.trade.order.bo.notify.PayResultSubOrderBO;
import com.tiancheng.trade.order.enums.*;
import com.tiancheng.trade.commom.web.feign.PaymentFeignService;
import com.tiancheng.trade.order.mapper.SubOrderMapper;
import com.tiancheng.trade.order.mapper.SubOrderStatusMapper;
import com.tiancheng.trade.order.model.*;
import com.tiancheng.trade.order.model.join.SubOrderJoin;
import com.tiancheng.trade.order.service.*;
import com.tiancheng.trade.commom.core.utils.DateTimeUtil;
import com.tiancheng.trade.order.util.ExcelBuildUtil;
import com.tiancheng.trade.order.util.ObjectConvertUtil;
import com.tiancheng.trade.order.util.cmq.queue.producer.VipMessageProducer;
import com.tiancheng.trade.order.util.helper.OrderIdHelper;
import com.tiancheng.trade.order.vo.admin.QuerySubOrderVO;
import com.tiancheng.trade.order.vo.admin.res.CouponDetailVO;
import com.tiancheng.trade.order.vo.admin.res.SubOrderDetailResVO;
import com.tiancheng.trade.order.vo.admin.res.SubOrderDetailVO;
import com.tiancheng.trade.order.vo.admin.res.SubOrderResVO;
import com.tiancheng.trade.order.vo.api.ReportOrderStatusVO;
import com.tiancheng.trade.order.vo.api.UpdateOrderVO;
import com.tiancheng.trade.order.vo.api.VerificationOrderVO;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目名称：trade-order
 * 类 名 称：SubOrderService
 * 类 描 述：子订单操作
 * 创建时间：2024-02-21 15:36
 * 创 建 人：liudong
 */
@Slf4j
@Service
public class SubOrderServiceImpl extends ServiceImpl<SubOrderMapper, SubOrder> implements SubOrderService {

    @Resource
    private SubOrderMapper subOrderMapper;
    @Resource
    private CouponService couponService;
    @Resource
    private RefundOrdersDetailService refundOrdersDetailService;
    @Resource
    private OrderService orderService;
    @Resource
    private SubOrderStatusService subOrderStatusService;
    @Resource
    private PaymentFeignService paymentFeignService;
    @Resource
    private OrderIdHelper orderIdHelper;
    @Resource
    private TallyService tallyService;
    @Resource
    private SubOrderStatusMapper subOrderStatusMapper;
    @Resource
    private MessageSubscribeService messageSubscribeService;
    @Resource
    private VipMessageProducer vipMessageProducer;

    @Override
    public PageInfo<SubOrderResVO> querySubOrderList(QuerySubOrderVO subOrderVO) {
        QueryWrapper<SubOrder> query = buildQuery(subOrderVO);
        query.orderByDesc("created_dt");
        PageInfo<SubOrder> pageInfo = subOrderMapper.find(query, subOrderVO.getCurrentPage(), subOrderVO.getPageSize());
        PageInfo<SubOrderResVO> pageRes = new PageInfo<>();
        List<SubOrderResVO> vos = pageInfo.getList().stream().map(subOrder ->
                ObjectConvertUtil.convert(subOrder, SubOrderResVO.class).get()).collect(Collectors.toList());
        vos.forEach(subOrderResVO -> subOrderResVO.setOrderSourceCN(OrderSourceEnum.getDesc(subOrderResVO.getOrderSource())));
        vos.forEach(subOrderResVO -> subOrderResVO.setSubOrderStatusCN(SubOrderStatusEnum.getDesc(subOrderResVO.getSubOrderStatus())));
        pageRes.setList(vos);
        pageRes.setPagination(pageInfo.getPagination());
        return pageRes;
    }

    private QueryWrapper<SubOrder> buildQuery(QuerySubOrderVO subOrderVO) {
        QueryWrapper<SubOrder> query = new QueryWrapper<>();
        if (StrUtil.isNotBlank(subOrderVO.getOrderId())) {
            query.eq("order_id", subOrderVO.getOrderId());
        }
        if (StrUtil.isNotBlank(subOrderVO.getSubOrderId())) {
            query.eq("sub_order_id", subOrderVO.getSubOrderId());
        }
        if (StrUtil.isNotBlank(subOrderVO.getOriginalSubOrderId())) {
            query.eq("original_sub_order_id", subOrderVO.getOriginalSubOrderId());
        }
        if (StrUtil.isNotBlank(subOrderVO.getMerchantName())) {
            query.like("merchant_name", subOrderVO.getMerchantName());
        }
        if (StrUtil.isNotBlank(subOrderVO.getProductName())) {
            query.like("product_name", subOrderVO.getProductName());
        }

        if (StrUtil.isNotBlank(subOrderVO.getOrderSource())) {
            query.eq("order_source", subOrderVO.getOrderSource());
        }
        if (StrUtil.isNotBlank(subOrderVO.getSubOrderStatus())) {
            query.eq("sub_order_status", subOrderVO.getSubOrderStatus());
        }
        if (StrUtil.isNotBlank(subOrderVO.getVerificationStatus())) {
            query.eq("verification_status", subOrderVO.getVerificationStatus());
        }
        if (!StringUtils.isEmpty(subOrderVO.getCreateTimeBegin()) && !StringUtils.isEmpty(subOrderVO.getCreateTimeEnd())) {
            query.between(
                    "created_dt",
                    LocalDateTime.of(subOrderVO.getCreateTimeBegin(), LocalTime.of(0, 0, 0)),
                    LocalDateTime.of(subOrderVO.getCreateTimeEnd(), LocalTime.of(23, 59, 59))
            );
        }
        if (subOrderVO.getVerificationTimeBegin() != null && subOrderVO.getVerificationTimeEnd() != null) {
            query.between(
                    "verification_time",
                    LocalDateTime.of(subOrderVO.getVerificationTimeBegin(), LocalTime.of(0, 0, 0)),
                    LocalDateTime.of(subOrderVO.getVerificationTimeEnd(), LocalTime.of(23, 59, 59))
            );
        }
        return query;
    }

    @Override
    public Result exportOrderList(QuerySubOrderVO vo, HttpServletResponse response) throws IOException {
        QueryWrapper<SubOrder> query = buildQuery(vo);
        query.orderByAsc("created_dt");
        if (vo.getCreateTimeBegin() == null || vo.getCreateTimeEnd() == null) {
            DateTime now = new DateTime();
            query.between("created_dt", DateUtil.beginOfMonth(now), DateUtil.endOfMonth(now));
        }
        query.select("order_id", "sub_order_id", "merchant_name", "product_name", "sub_order_status", "sub_order_amount"
                , "pay_amount", "discount", "created_dt", "product_cost", "refund_amount");
        List<SubOrder> subOrders = subOrderMapper.selectList(query);
        if (subOrders.isEmpty()) return Result.success("当前查询条件暂无数据");

        // 查询主订单
        Map<String, List<Order>> orders = orderService.findByOrderIds(
                subOrders.stream().map(SubOrder::getOrderId).collect(Collectors.toSet())
        ).stream().collect(Collectors.groupingBy(Order::getOrderId));

        ExportExcelBO exportExcelBO = new ExportExcelBO();
        exportExcelBO.setFileName("子订单导出");
        exportExcelBO.setSheets(new ArrayList<ExportExcelBO.Sheet>());

        // 子订单导出数据
        ExportExcelBO.Sheet subOrderSheet = new ExportExcelBO.Sheet();
        subOrderSheet.setSheetName("子订单");
        List<ExportSubOrderBo> subOrderData = new ArrayList<>(subOrders.size());
        // 产生退款子订单号
        Set<String> refundSubOrderIds = new HashSet<String>();
        Set<String> refundOrderIds = new HashSet<String>();
        subOrders.forEach(subOrder -> {
            String orderId = subOrder.getOrderId();
            Order order = orders.getOrDefault(orderId, Collections.emptyList()).stream().findFirst().orElse(new Order());
            subOrderData.add(new ExportSubOrderBo(
                    subOrders.indexOf(subOrder) + 1,
                    orderId,
                    subOrder.getSubOrderId(),
                    order.getFlowId(),
                    OrderSourceEnum.getDesc(order.getOrderSource()),
                    subOrder.getMerchantName(),
                    subOrder.getProductName(),
                    SubOrderStatusEnum.getDesc(subOrder.getSubOrderStatus()),
                    NumberUtil.div(Optional.ofNullable(subOrder.getSubOrderAmount()).orElse(0), Integer.valueOf(100)),
                    NumberUtil.div(Optional.ofNullable(subOrder.getPayAmount()).orElse(0), Integer.valueOf(100)),
                    NumberUtil.div(Optional.ofNullable(subOrder.getDiscount()).orElse(0), Integer.valueOf(100)),
                    subOrder.getCreatedDt() != null ? subOrder.getCreatedDt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")) : "无",
                    NumberUtil.div(Optional.ofNullable(subOrder.getProductCost()).orElse(0), Integer.valueOf(100))

            ));
            if (null != subOrder.getRefundAmount() && subOrder.getRefundAmount() > 0) {
                refundSubOrderIds.add(subOrder.getSubOrderId());
                refundOrderIds.add(subOrder.getOrderId());
            }
        });
        subOrderSheet.setData(subOrderData);
        exportExcelBO.getSheets().add(subOrderSheet);
        // 查询退款订单
        if (CollectionUtils.isNotEmpty(refundOrderIds) && CollectionUtils.isNotEmpty(refundSubOrderIds)) {
            List<RefundOrdersDetail> refundOrdersDetails = refundOrdersDetailService.querySuccessRefundBySubOrderIds(refundOrderIds, refundSubOrderIds);
            // 子订单退款导出数据
            ExportExcelBO.Sheet subOrderRefundSheet = new ExportExcelBO.Sheet();
            subOrderRefundSheet.setSheetName("退款子订单");
            List<ExportSubOrderRefundBo> subOrderRefundBO = new ArrayList<>(refundOrdersDetails.size());
            for (RefundOrdersDetail refundOrdersDetail : refundOrdersDetails) {
                subOrderRefundBO.add(new ExportSubOrderRefundBo(
                        refundOrdersDetail.getOrderId(),
                        refundOrdersDetail.getSubOrderId(),
                        refundOrdersDetail.getPayFlowId(),
                        refundOrdersDetail.getFlowId(),
                        NumberUtil.div(Optional.ofNullable(refundOrdersDetail.getSubOrderAmount()).orElse(0), Integer.valueOf(100)),
                        refundOrdersDetail.getProductName(),
                        NumberUtil.div(Optional.ofNullable(refundOrdersDetail.getRefundApplyAmount()).orElse(0), Integer.valueOf(100)),
                        NumberUtil.div(Optional.ofNullable(refundOrdersDetail.getRefundAmount()).orElse(0), Integer.valueOf(100)),
                        refundOrdersDetail.getRefundTime() != null ? refundOrdersDetail.getRefundTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")) : "无"
                ));
            }
            subOrderRefundSheet.setData(subOrderRefundBO);
            exportExcelBO.getSheets().add(subOrderRefundSheet);
        }
        ExcelBuildUtil.exportExcel(exportExcelBO, response);
        return Result.success("导出成功");
    }

    @Override
    public List<SubOrder> create(List<SubOrderBO> subOrderBOS) throws BusinessException {
        List<SubOrder> subOrders = subOrderBOS.stream().map(subOrderBO -> {
            SubOrder subOrder = ObjectConvertUtil.convert(subOrderBO, SubOrder.class).get();
            subOrder.setSubOrderStatus(OrderStatusEnum.waiting_pay.getCode());
            subOrder.setPayAmount(subOrder.getSubOrderAmount() - subOrder.getPlatformDiscount());//子订单支付金额=子订单应收金额-子订单平台优惠金额
            subOrder.setCreatedDt(subOrderBO.getCreateTime());
            subOrder.setRefundAmount(0);
            return subOrder;
        }).collect(Collectors.toList());

        final int i = subOrderMapper.saveBatch(subOrders);
        BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(i > 0, "创建子订单失败！");
        return subOrders;
    }

    @Override
    public List<PayResultSubOrderBO> paid(String orderId, List<PaySubFlowResultMsgBO> subFlows, Integer couponAmount, String payStatus) throws BusinessException {
        if (CollectionUtils.isEmpty(subFlows)) {
            log.error("支付结果修改错误，主订单集合为空");
            return Collections.emptyList();
        }
        log.info("修改子订单支付状态,orderId:{},subFlows:{}", orderId, subFlows);
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.eq("order_id", orderId);
        conditions.in("sub_order_id", subFlows.stream().map(PaySubFlowResultMsgBO::getSubOrderId).collect(Collectors.toList()));
        conditions.orderByAsc("created_dt");
        List<SubOrder> subOrders = subOrderMapper.selectList(conditions);
        //conditions.eq("sub_order_status", OrderStatusEnum.waiting_pay.getCode());
        List<PayResultSubOrderBO> result = new ArrayList<>();
        if (null == couponAmount || couponAmount <= 0) {
            log.info("没有渠道优惠");
            final List<SubOrder> updateSubOrders = new ArrayList<>();
            for (SubOrder subOrder : subOrders) {
                final PaySubFlowResultMsgBO subFlowResultMsgBO = subFlows.stream().filter(sf -> sf.getSubOrderId().equals(subOrder.getSubOrderId())).findFirst().get();
                final PayResultSubOrderBO payResultSubOrderBO = new PayResultSubOrderBO();
                payResultSubOrderBO.setOrderId(subOrder.getOrderId());
                payResultSubOrderBO.setSubOrderId(subOrder.getSubOrderId());
                payResultSubOrderBO.setSubFlowId(subFlowResultMsgBO.getSubFlowId());
                payResultSubOrderBO.setMerchantCode(subOrder.getMerchantCode());
                payResultSubOrderBO.setMerchantName(subOrder.getMerchantName());
                payResultSubOrderBO.setSubOrderAmount(subOrder.getSubOrderAmount());
                payResultSubOrderBO.setPayAmount(subOrder.getPayAmount());
                payResultSubOrderBO.setIsCoupon(subOrder.getIsCoupon());
                payResultSubOrderBO.setDiscount(subOrder.getDiscount());
                result.add(payResultSubOrderBO);

                SubOrder updateSubOrder = new SubOrder();
                updateSubOrder.setId(subOrder.getId());
                updateSubOrder.setSubOrderStatus(payStatus);
                updateSubOrder.setSubFlowId(subFlowResultMsgBO.getSubFlowId());
                updateSubOrders.add(updateSubOrder);
            }
            this.updateBatchById(updateSubOrders);
            return result;
        }
        if (CollectionUtils.isNotEmpty(subOrders)) {
            log.info("查询到子订单：{}", JsonUtil.toJsonString(subOrders));
        }
        int sumAmount = subOrders.stream().mapToInt(SubOrder::getSubOrderAmount).sum();
        int divideTotal = 0;
        int divide = 0;
        for (int i = 0; i < subOrders.size(); i++) {
            SubOrder subOrder = subOrders.get(i);
            final PaySubFlowResultMsgBO subFlowResultMsgBO = subFlows.stream().filter(sf -> sf.getSubOrderId().equals(subOrder.getSubOrderId())).findFirst().get();
            SubOrder updateSubOrder = new SubOrder();
            //子订单总优惠金额=子订单平台优惠金额+子订单渠道优惠金额
            if (i == subOrders.size() - 1) {
                divide = couponAmount - divideTotal;
                updateSubOrder.setDiscount(subOrder.getPlatformDiscount() + divide);
            } else {
                // 1、计算子订单所占总金额的比例，小数点后取10位，然后截取
                // 2、总优惠金额*子订单比例，然后四舍五入取整
                divide = BigDecimal.valueOf(subOrder.getSubOrderAmount()).
                        divide(BigDecimal.valueOf(sumAmount), 10, BigDecimal.ROUND_DOWN)
                        .multiply(BigDecimal.valueOf(couponAmount)).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
                updateSubOrder.setDiscount(subOrder.getPlatformDiscount() + divide);
                divideTotal += (divide);
            }
            log.info("子订单均摊渠道优惠金额，子订单：{}，渠道优惠：{}，优惠总金额：{}", subOrder.getSubOrderId(), divide, updateSubOrder.getDiscount());
            // 实付金额
            updateSubOrder.setSubFlowId(subFlowResultMsgBO.getSubFlowId());
            updateSubOrder.setIsCoupon(1);
            updateSubOrder.setPayAmount(subOrder.getSubOrderAmount() - updateSubOrder.getDiscount());
            updateSubOrder.setSubOrderStatus(payStatus);
            updateSubOrder.setSubFlowId(subFlowResultMsgBO.getSubFlowId());
            QueryWrapper<SubOrder> updateConditions = new QueryWrapper<>();
            updateConditions.eq("id", subOrder.getId());
            updateConditions.eq("sub_order_id", subOrder.getSubOrderId());
            updateConditions.eq("order_id", subOrder.getOrderId());
            subOrderMapper.update(updateSubOrder, updateConditions);

            final PayResultSubOrderBO payResultSubOrderBO = new PayResultSubOrderBO();
            payResultSubOrderBO.setOrderId(subOrder.getOrderId());
            payResultSubOrderBO.setSubOrderId(subOrder.getSubOrderId());
            payResultSubOrderBO.setSubFlowId(subFlowResultMsgBO.getSubFlowId());
            payResultSubOrderBO.setMerchantCode(subOrder.getMerchantCode());
            payResultSubOrderBO.setMerchantName(subOrder.getMerchantName());
            payResultSubOrderBO.setSubOrderAmount(subOrder.getSubOrderAmount());
            payResultSubOrderBO.setPayAmount(updateSubOrder.getPayAmount());
            payResultSubOrderBO.setIsCoupon(updateSubOrder.getIsCoupon());
            payResultSubOrderBO.setDiscount(updateSubOrder.getDiscount());
            result.add(payResultSubOrderBO);
        }
        return result;
    }

    @Override
    @Transactional
    public List<SubOrder> updateAmount(UpdateOrderVO updateOrderVO) throws BusinessException {
        List<SubOrder> subOrders = this.findByOrderId(updateOrderVO.getOrderId());
        BusinessErrorInfoEnum.ORDER_UPDATE_SUB_ORDER_NO.assertIsTrue(subOrders.size() == updateOrderVO.getSubOrders().size());

        Map<String, Integer> updateAmountMap = updateOrderVO.getSubOrders().stream().collect(
                Collectors.toMap(UpdateOrderVO.SubOrder::getSubOrderId, UpdateOrderVO.SubOrder::getSubOrderAmount));
        for (SubOrder subOrder : subOrders) {
            if (!updateAmountMap.containsKey(subOrder.getSubOrderId())) continue;

            SubOrder updateSubOrder = new SubOrder();
            updateSubOrder.setSubOrderAmount(updateAmountMap.get(subOrder.getSubOrderId()));
            int payAmount = updateSubOrder.getSubOrderAmount() - subOrder.getDiscount();
            updateSubOrder.setPayAmount(payAmount < 0 ? 0 : payAmount);
            updateSubOrder.setLastUpdDt(LocalDateTime.now());

            QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
            conditions.eq("order_id", updateOrderVO.getOrderId());
            conditions.eq("sub_order_id", subOrder.getSubOrderId());
            subOrderMapper.update(updateSubOrder, conditions);

            subOrder.setSubOrderAmount(updateSubOrder.getSubOrderAmount());
            subOrder.setPayAmount(updateSubOrder.getPayAmount());
        }
        return subOrders;
    }

    @Override
    public List<SubOrder> find(String[] orderIds) {
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.in("order_id", orderIds);
        return subOrderMapper.selectList(conditions);
    }

    @Override
    public List<SubOrder> findCanRefund(String orderId, String[] subOrderIds) {
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.eq("order_id", orderId);
        conditions.in("sub_order_id", subOrderIds);
        conditions.orderByAsc("id");
        return subOrderMapper.selectList(conditions);
    }

    @Override
    public SubOrder findBySubId(String subId) {
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.in("sub_order_id", subId);
        return subOrderMapper.selectOne(conditions);
    }

    @Override
    public int refundIng(String[] subOrderIds) {
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.in("sub_order_id", subOrderIds);

        SubOrder updateSubOrder = new SubOrder();
        updateSubOrder.setRefundStatus(RefundStatusEnum.ing.getCode());
        return subOrderMapper.update(updateSubOrder, conditions);
    }

    @Override
    public int refund(List<SubOrderRefundBO> subOrderRefundBOS) {
        return subOrderMapper.refundOrdersDetail(subOrderRefundBOS);
    }

    @Override
    public List<SubOrder> findByOrderId(String orderId) {
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.eq("order_id", orderId);
        return subOrderMapper.selectList(conditions);
    }

    private SubOrderStatus querySubOrderStatus(SubOrder subOrder) {
        QueryWrapper<SubOrderStatus> conditions = new QueryWrapper<>();
        conditions.eq("order_source", subOrder.getOrderSource());
        conditions.eq("biz_status", subOrder.getBizStatus());
        return subOrderStatusMapper.selectOne(conditions);
    }

    /**
     * 功能描述: 根据子订单号查询详情
     *
     * @param:
     * @return:
     * @auther: LiuDong
     * @date: 10:06 2024/4/2
     */
    @Override
    public SubOrderDetailResVO findSubOrderBySubId(String subId) {
        SubOrderDetailResVO detailBO = new SubOrderDetailResVO();
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.eq("sub_order_id", subId);
        List<Coupon> coupons = null;
        List<RefundOrdersDetail> refundOrdersDetails = null;
        Order order = null;
        List<CouponDetailVO> couponVos = null;
        SubOrderDetailVO orderDetailVO = null;
        SubOrderStatus subOrderStatus = null;
        SubOrder subOrder = subOrderMapper.selectOne(conditions);
        if (null != subOrder) {
            orderDetailVO = ObjectConvertUtil.convert(subOrder, SubOrderDetailVO.class).get();
            coupons = couponService.getSubCouponList(subOrder.getSubOrderId());
            refundOrdersDetails = refundOrdersDetailService.getSubRefund(subOrder.getSubOrderId());
            order = orderService.get(subOrder.getOrderId());
            orderDetailVO.setPayCreateTime(order.getCreatedDt());
            orderDetailVO.setPayTime(order.getPayTime());
            orderDetailVO.setFlowId(order.getFlowId());
            orderDetailVO.setPaymentId(order.getPaymentId());
            orderDetailVO.setCouponNum(0);
            subOrderStatus = querySubOrderStatus(subOrder);
        }
        if (null != subOrderStatus) {
            orderDetailVO.setBizStatus(subOrderStatus.getBizStatus());
            orderDetailVO.setBizStatusName(subOrderStatus.getBizStatusName());
        }
        detailBO.setRefundOrdersDetails(refundOrdersDetails);
        if (CollectionUtils.isNotEmpty(coupons)) {
            orderDetailVO.setCouponNum(coupons.size());
            orderDetailVO.setIsCoupon(true);
            couponVos = coupons.stream().map(couponBO ->
                    ObjectConvertUtil.convert(couponBO, CouponDetailVO.class).get()).collect(Collectors.toList());
            couponVos.stream().forEach(couponDetailVO -> couponDetailVO.setIsCoupon(true));
            couponVos.stream().forEach(couponDetailVO -> couponDetailVO.setCouponTypeCN(CouponTypeEnum.getDesc(couponDetailVO.getCouponType())));
            couponVos.stream().forEach(couponDetailVO -> couponDetailVO.setDiscountSourceCN(OrderSourceEnum.getDesc(couponDetailVO.getDiscountSource())));
        }
        orderDetailVO.setSubOrderStatusCN(SubOrderStatusEnum.getDesc(orderDetailVO.getSubOrderStatus()));
        orderDetailVO.setOrderSourceCN(OrderSourceEnum.getDesc(subOrder.getOrderSource()));
        detailBO.setSubOrderDetailVO(orderDetailVO);
        detailBO.setCoupons(couponVos);
        return detailBO;
    }

    @Override
    public void statusFlow(String orderId, String[] subOrderId, String bizStatus) throws BusinessException {
        Order order = orderService.get(orderId);
        BusinessErrorInfoEnum.ORDER_STATUS_FLOW_NO_DATA.assertNotNull(order);

        Map<String, String> statusMap = subOrderStatusService.find(order.getOrderSource(), bizStatus);
        BusinessErrorInfoEnum.ORDER_STATUS_FLOW_NO_DATA.assertIsTrue(statusMap != null && statusMap.containsKey(bizStatus));

        // 根据业务侧状态取出订单中心对应的状态值，其中还包括是否核销，格式为SC:1
        String[] values = statusMap.get(bizStatus).split(":");
        // 中台子订单状态
        String subOrderStatus = values[0];
        // 核销状态
        String verification = values[1];
        // 判断状态，如果对应交易中台为IG&不需要核销，则不处理了
        if (!StringUtils.isEmpty(subOrderStatus) && SubOrderStatusEnum.ing.getCode().equals(subOrderStatus)
                && !StringUtils.isEmpty(verification) && "0".equals(verification)) {
            log.info("对应子订单状态IG，且不核销，不处理");
            return;
        }

    }

    private void vipVerificationMsg(Order order, List<SubOrder> verificationSubOrders) {
        if (CollectionUtils.isNotEmpty(verificationSubOrders)) {
            VipMsgBO vipMsgBO = new VipMsgBO();
            vipMsgBO.setUid(order.getUid());
            vipMsgBO.setType("consumption");
            vipMsgBO.setAction(VipMessageProducer.ACTION_VERIFICATION);
            vipMsgBO.setScene(order.getOrderSource());
            vipMsgBO.setTime(DateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss"));
            Map<String, Object> orderMap = new HashMap<>();
            orderMap.put("order_id", order.getOrderId());

            final List<Map<String, Object>> sos = new ArrayList<>(verificationSubOrders.size());
            for (SubOrder s : verificationSubOrders) {
                Map<String, Object> subOrder = new HashMap<>();
                subOrder.put("sub_order_id", s.getSubOrderId());
                subOrder.put("amount", s.getPayAmount());
                sos.add(subOrder);
            }
            orderMap.put("list", sos);
            vipMsgBO.setExtend(orderMap);
            log.info("核销订单，释放锁定的会员权益:{}", JsonUtil.toJsonString(vipMsgBO));
            final boolean sec = vipMessageProducer.sendVipMsg(vipMsgBO);
            if (!sec) {
                vipMessageProducer.sendVipMsg(vipMsgBO);
            }
        }
    }

    @Override
    public SubOrderJoin getWithJoin(String subOrderId) {
        SubOrderJoin subOrderJoin = subOrderMapper.getWithJoin(subOrderId);
        if (null != subOrderJoin && CollectionUtils.isNotEmpty(subOrderJoin.getCoupons())) {
            subOrderJoin.setIsCoupon(1);
        }
        return subOrderJoin;
    }

    @Override
    public List<SubOrder> findSubOrderByDate(String date) {
        return subOrderMapper.findSubOrderByDate(date);
    }

    @Override
    public List<SubOrder> find(String orderId, String[] subOrderIds) {
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.eq("order_id", orderId);
        conditions.in("sub_order_id", subOrderIds);
        return subOrderMapper.selectList(conditions);
    }

    @Override
    public Map<String, Object> verification(VerificationOrderVO date) {
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.in("sub_order_id", date.getSubOrderId());
        conditions.isNull("verification_time");
        List<SubOrder> subOrders = subOrderMapper.selectList(conditions);
        if (CollectionUtils.isEmpty(subOrders)) {
            return null;
        }
        List<Order> orders = orderService.findByOrderIds(subOrders.stream().map(SubOrder::getOrderId).collect(Collectors.toSet()));
        if (CollectionUtils.isEmpty(orders)) {
            return null;
        }

        List<SubOrder> updateOrders = new ArrayList<>();
        Set<String> failSubOrders = new HashSet<>();
        Set<String> successSubOrders = new HashSet<>();
        /*for (SubOrder subOrder : subOrders) {
            Order order = orders.stream().filter(o -> o.getOrderId().equals(subOrder.getOrderId())).collect(Collectors.toList()).get(0);
            if (order.getPayStatus().equals(OrderPayStatusEnum.un_pay.getCode())) {
                failSubOrders.add(subOrder.getSubOrderId());
                continue;
            }
            VerificationOrderDTO verificationOrderDTO = new VerificationOrderDTO();
            verificationOrderDTO.setUid(StringUtils.isEmpty(order.getBuyerUid()) ? order.getUid() : order.getBuyerUid());
            verificationOrderDTO.setFlowId(order.getFlowId());
            verificationOrderDTO.setSubOrderId(subOrder.getSubOrderId());
            verificationOrderDTO.setAmount(subOrder.getPayAmount());
            verificationOrderDTO.setVerificationId(orderIdHelper.getVerificationId(order.getUid()));
            Result result = paymentService.verification(verificationOrderDTO);
            //BusinessErrorInfoEnum.ORDER_STATUS_FLOW_VERIFICATION_ERROR.assertIsTrue(result.getRet() == 0);
            SubOrder updateSubOrder = new SubOrder();
            updateSubOrder.setSubOrderId(subOrder.getSubOrderId());
            if (result.getRet() == 0) {
                updateSubOrder.setVerificationStatus(VerificationStatusEnum.SC.getCode());
                updateSubOrder.setVerificationTime(LocalDateTime.now());
                if (subOrder.getVerificationTime() == null && order.getPayChannel().equals(PayChannelEnum.CMB.getCode())) {
                    // 创建核销成功后，将核销数据cmq给对账中心
                    tallyService.verification(verificationOrderDTO.getVerificationId(), verificationOrderDTO.getAmount(),
                            updateSubOrder.getVerificationTime(), subOrder.getSubOrderId());
                }
                successSubOrders.add(updateSubOrder.getSubOrderId());
            } else {
                log.error("订单核销失败，核销结果：{}", result);
                updateSubOrder.setVerificationStatus(VerificationStatusEnum.FL.getCode());
                updateSubOrder.setVerificationTime(null);
                failSubOrders.add(subOrder.getSubOrderId());
            }
            updateOrders.add(updateSubOrder);
        }
        if (CollectionUtils.isNotEmpty(updateOrders)) {
            subOrderMapper.updateVerification(updateOrders);
        }*/
        Map<String, Object> result = new HashMap<>();
        result.put("fail_sub_order", failSubOrders);
        result.put("success_sub_order", successSubOrders);
        return result;
    }

    @Override
    public List<SubOrder> verificationErrorOrder() {
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        conditions.eq("verification_status", VerificationStatusEnum.FL.getCode());
        conditions.select("sub_order_id");
        return subOrderMapper.selectList(conditions);
    }

    @Override
    public void reportOrderStatus(ReportOrderStatusVO data) {
        messageSubscribeService.statusFlowForSubOrderByInterface(data.getOrderId(), data.getBizStatus(), data.getSubOrderId());
    }

    @Override
    public List<ScrmSubOrders> queryScrmSubOrders(Collection<String> orderIds, Collection<String> subOrderIds) {
        if (CollectionUtils.isEmpty(orderIds) && CollectionUtils.isEmpty(subOrderIds)) {
            return Collections.emptyList();
        }
        QueryWrapper<SubOrder> conditions = new QueryWrapper<>();
        if (CollectionUtils.isNotEmpty(orderIds)) {
            conditions.in("order_id", orderIds);
        }

        if (CollectionUtils.isNotEmpty(subOrderIds)) {
            conditions.in("sub_order_id", subOrderIds);
        }
        conditions.select("order_id", "sub_order_id", "product_code", "product_name", "product_count", "pay_amount", "sub_order_amount", "discount");
        final List<SubOrder> subOrders = subOrderMapper.selectList(conditions);
        List<ScrmSubOrders> scrmSubOrders = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(subOrders)) {
            subOrders.forEach(s -> {
                final ScrmSubOrders so = new ScrmSubOrders();
                so.setOrderId(s.getOrderId());
                so.setChildOrderId(s.getSubOrderId());
                so.setProductId("1");
                so.setTitle(s.getProductName());
                so.setNum(s.getProductCount().toString());
                so.setPrice(String.valueOf(NumberUtil.div(Optional.ofNullable(s.getSubOrderAmount()).orElse(0), NumberUtil.mul(s.getProductCount(), Integer.valueOf(100)), 2)));
                so.setTotalPayamount(String.valueOf(NumberUtil.div(Optional.ofNullable(s.getPayAmount()).orElse(0), Integer.valueOf(100), 2)));
                so.setDiscountFee(String.valueOf(NumberUtil.div(Optional.ofNullable(s.getDiscount()).orElse(0), Integer.valueOf(100), 2)));
                so.setTotalFee(String.valueOf(NumberUtil.div(Optional.ofNullable(s.getSubOrderAmount()).orElse(0), Integer.valueOf(100), 2)));
                so.setOrderStatus("Trade_Success");
                so.setRefundStatus("NoRefund");
                scrmSubOrders.add(so);
            });
        }
        return scrmSubOrders;
    }

}
